package example.hello_security.controller;

import cn.hutool.json.JSONUtil;
import example.hello_security.config.JwtConfig;
import example.hello_security.entity.LoginsUserDetail;
import example.hello_security.result.Result;
import example.hello_security.service.RedisStore;
import example.hello_security.utils.JwtUtil;
import jakarta.annotation.Resource;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;


import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


@Slf4j
@RestController
public class HelloController {

    @Resource
    JwtUtil jwtUtil;

    @Resource
    AuthenticationManager authenticationManager;

    @Resource
    JwtConfig jwtConfig;

    @Resource
    RedisStore redisStore;


    /**
     * description 测试方法，测试令牌是否有效
     * @author zken
     * CreateDate 2024/10/28 14:51:43
     */
    @GetMapping("/hello")
    public Result<String> hello() {
        return Result.success("hello world");
    }


    /**
     * description 测试方法，测试CEO身份是否验证成功
     * @author zken
     * CreateDate 2024/10/28 14:51:59
     */
    @PreAuthorize("hasAnyRole('ceo')")
    @GetMapping("/hello-CEO")
    public Result<String> helloCEO() {
        return Result.success("golden CEO !!! welcome..");
    }

    /**
     * description 测试方法，测试CTO身份是否识别成功
     * @author zken
     * CreateDate 2024/10/28 14:52:20
     */
    @PreAuthorize("hasAnyRole('cto')")
    @GetMapping("/hello-CTO")
    public Result<String> helloCTO() {
        return Result.success("platinum CTO !!! welcome..");
    }

    /**
     * description 测试方法，同时拥有ceo和cto两种身份才可以访问
     * @author zken
     * CreateDate 2024/10/28 14:53:42
     */
    @PreAuthorize("hasAnyRole('cto') and hasAnyRole('ceo')")
    @GetMapping("/hello-CTO-and-CEO")
    public Result<String> helloCtoAndCeo() {
        return Result.success("Diamond CTO plus CEO !!! welcome..");
    }


    /**
     * description 测试方法，同时拥有ceo和cto两种身份才可以访问
     * @author zken
     * CreateDate 2024/10/28 14:53:42
     */
    @PreAuthorize("hasAnyRole('cto','ceo')")
    @GetMapping("/hello-CTO-or-CEO")
    public Result<String> helloCtoOrCeo() {
        return Result.success("Elegant CTO or CEO !!! welcome..");
    }


    /**
     * description 测试方法，测试含有权限删除
     * @author zken
     * CreateDate 2024/10/28 14:56:22
     */
    @PreAuthorize("hasAnyAuthority('delete')")
    @GetMapping("/hello-delete")
    public Result<String> helloDelete() {
        return Result.success("You can delete something");
    }


    /**
     * description 测试方法，测试含有权限READ（读取）
     * @author zken
     * CreateDate 2024/10/28 14:56:22
     */
    @PreAuthorize("hasAnyAuthority('read')")
    @GetMapping("/hello-read")
    public Result<String> helloRead() {
        return Result.success("You can read something");
    }


    /**
     * description 测试方法，测试admin身份识别
     * @author zken
     * CreateDate 2024/10/28 14:52:35
     */
    @PreAuthorize("hasAnyRole('admin')")
    @GetMapping("/hello-Admin")
    public Result<String> helloAdmin() {
        return Result.success("helloAdmin !!! welcome..");
    }


    /**
     * 登录方法
     * description 由于是测试，所以token部分暂时不剥离出来
     * @author zken
     * CreateDate 2024/10/27 16:54:17
     */
    @PostMapping("/login")
    public Result<String> login(Integer phone, String password) {
        long ttlInSeconds = 3600 * 30L;

        try {
            // 进行认证
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(phone, password);
            // 如果认证错误，此方法会抛出异常
            Authentication authentication = authenticationManager.authenticate(authenticationToken);
            if (Objects.isNull(authentication)) {
                return Result.error("用户名或者密码错误");
            }
            // 生成token，准备返回
            LoginsUserDetail userDetail = (LoginsUserDetail) authentication.getPrincipal();
            userDetail.getUser().setPassword("");
            Map<String, Object> claims = new HashMap<>();
            claims.put("phone", userDetail.getUser().getPhone());
            String token = jwtUtil.createToken(claims, ttlInSeconds, ChronoUnit.SECONDS);
            // 存入redis中备用
            String key = jwtConfig.jwtRedisKeyPrefix + token;
            String json = JSONUtil.toJsonStr(userDetail);
            redisStore.set(key, json, ttlInSeconds);

            return Result.success(token);
        } catch (Exception e) {
            log.error("错误信息:{},错误堆栈信息:{}", e.getMessage(), e.getStackTrace());
            return Result.error("登录异常");
        }
    }

}
